package org.my.spring.agent.mcp.core.utils;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserType;
import com.microsoft.playwright.Playwright;
import com.microsoft.playwright.options.Cookie;
import com.microsoft.playwright.options.SameSiteAttribute;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.my.spring.agent.mcp.core.config.AgentPlaywrightConfig;
import org.my.spring.agent.mcp.core.domain.constants.PlaywrightConstant;
import org.my.spring.agent.mcp.core.domain.enums.BroswerEnum;
import org.springframework.util.ObjectUtils;
import org.apache.http.client.CookieStore;
import org.apache.http.impl.client.BasicCookieStore;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class PlaywrightUtil {
    private static final Map<String, Browser> bwCacheMap = new ConcurrentHashMap<>();

    public static AgentPlaywrightConfig.BrowserModel getBrowserModel(AgentPlaywrightConfig playwrightConfig, String bwtype) {
        return playwrightConfig.getBrowsers().stream()
                .filter(b -> b.getType().equals(bwtype))
                .findFirst()
                .orElse(new AgentPlaywrightConfig.BrowserModel());
    }

    public static Browser initBrowser(AgentPlaywrightConfig.BrowserModel browserModel) {
        //设置NODE路径
        System.setProperty("playwright.cli.dir", browserModel.getNodePath());
        Map<String, String> map = new HashMap<>();
        //跳过Node版本检查
        map.put("NODE_SKIP_PLATFORM_CHECK", "1");
        //跳过下载浏览器
        map.put("PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD", "1");

        Playwright playwright = Playwright.create(new Playwright.CreateOptions().setEnv(map));

        if (BroswerEnum.FIRFOX.getName().equals(browserModel.getType())) {
            BrowserType firefox = playwright.firefox();
            return firefox.launch(new BrowserType.LaunchOptions().setHeadless(browserModel.isHeadless()).setExecutablePath(Paths.get(browserModel.getExecPath())));
        }

        BrowserType chromium = playwright.chromium();
        return chromium.launch(new BrowserType.LaunchOptions().setHeadless(browserModel.isHeadless())
                .setDevtools(browserModel.isDevtools())
                .setChromiumSandbox(browserModel.isSandbox()).setExecutablePath(Paths.get(browserModel.getExecPath()))
                .setArgs(Arrays.asList("--user-agent=" + PlaywrightConstant.USER_AGENT, "--enable-automation=true", "--allow-running-insecure-content", "--disable-web-security", "--allow-insecure-locahost", "--disable-blink-features=AutomationControlled", "--proxy-bypass-list=*", "--proxy-server='direct://'")));
    }

    //bw
    public static void addCacheBrowser(String key, Browser browser) {
        bwCacheMap.put(key, browser);
    }

    public static Browser getCacheBrowser(String key) {
        log.info("bwCacheMap: {} ", bwCacheMap);
        return bwCacheMap.get(key);
    }
    public static Map<String, Browser> getCacheBrowserMap() {
        return bwCacheMap;
    }

    public static boolean hasCacheBrowser(String key) {
        return bwCacheMap.containsKey(key);
    }


    //转换为pw的cookie
    public static List<Cookie> getPlaywrightCookies(List<org.apache.http.cookie.Cookie> cookieList) {
        List<Cookie> cookies = new ArrayList<>();
        if (ObjectUtils.isEmpty(cookieList)) {
            return cookies;
        }
        for (org.apache.http.cookie.Cookie cookie : cookieList) {
            cookies.add(initPlaywrightCookie(cookie));
        }
        return cookies;
    }

    //JSONARRAY转换为pw的cookie
    public static List<Cookie> getPlaywrightCookies(JSONArray cookieList) {
        List<Cookie> cookies = new ArrayList<>();
        if (ObjectUtils.isEmpty(cookieList)) {
            return cookies;
        }

        int csize = cookieList.size();
        for (int i = 0; i < csize; i++) {
            JSONObject cookiesJSON = cookieList.getJSONObject(i);
            String cookieName = cookiesJSON.getString("name");
            String domain = cookiesJSON.getString("domain");

            BasicClientCookie cookie = new BasicClientCookie(cookieName, cookiesJSON.getString("value"));
            cookie.setDomain(domain);
            cookie.setPath(cookiesJSON.getString("path"));
            cookie.setAttribute("expires", cookiesJSON.getString("expires"));
            cookie.setSecure(cookiesJSON.getBoolean("secure"));
            cookie.setAttribute("httpOnly", "false");
            cookie.setAttribute("url", cookiesJSON.getString("url"));

            cookies.add(initPlaywrightCookie(cookie));
        }
        return cookies;
    }

    //pw转换为JSONARRAY的cookie
    public static JSONArray getJSONArrayCookies(List<Cookie> cookieList) {
        JSONArray cookies = new JSONArray();
        if (ObjectUtils.isEmpty(cookieList)) {
            return cookies;
        }

        for (Cookie cookiesJSON : cookieList) {
            cookies.add(initCookie(cookiesJSON));
        }
        return cookies;
    }

    //pw cookie转换为cookiestore
    public static CookieStore getCookieStore(List<Cookie> cookies) {
        CookieStore cookieStore = new BasicCookieStore();
        if (!ObjectUtils.isEmpty(cookies)) {
            for (Cookie cookiesJSON : cookies) {
                cookieStore.addCookie(initCookie(cookiesJSON));
            }
        }
        return cookieStore;
    }

    private static BasicClientCookie initCookie(Cookie cookiesJSON) {
        String cookieName = cookiesJSON.name;
        String domain = cookiesJSON.domain;
        BasicClientCookie cookie = new BasicClientCookie(cookieName, cookiesJSON.value);
        cookie.setDomain(domain);
        cookie.setPath(cookiesJSON.path);
        cookie.setAttribute("expires", cookiesJSON.expires + "");
        cookie.setSecure(cookiesJSON.secure);
        cookie.setAttribute("httpOnly", "");
        cookie.setAttribute("url", cookiesJSON.url);
        return cookie;
    }

    private static Cookie initPlaywrightCookie(org.apache.http.cookie.Cookie cookie) {
        Cookie msCookie = new Cookie(cookie.getName(), cookie.getValue());
        msCookie.setDomain(cookie.getDomain());
        msCookie.setPath(cookie.getPath());
        msCookie.setExpires(-1);
        msCookie.setSecure(cookie.isSecure());
        msCookie.setHttpOnly(false);
        msCookie.setSameSite(SameSiteAttribute.LAX);
        return msCookie;
    }
}
